package com.ndp.fb.walle.controller;

import com.alibaba.fastjson.JSON;
import com.ndp.fb.model.report.param.EcReportForABTestInputParam;
import com.ndp.fb.model.report.param.EcReportInputParam;
import com.ndp.fb.rdb.model.User;
import com.ndp.fb.util.ListUtil;
import com.ndp.fb.util.StringUtil;
import com.ndp.fb.walle.business.EcReportService;
import com.ndp.fb.walle.business.EcService;
import com.ndp.fb.walle.util.ExcelUtil;
import com.ndp.fb.walle.util.Week;
import com.ndp.fb.walle.util.WeekUtil;
import com.restfb.json.JsonObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by dangw on 2016/4/29.
 */
@RestController
@RequestMapping("/ecReport")
public class EcReportController {

    Logger logger = LoggerFactory.getLogger(EcFontController.class);

    private static String[] EXPORT_FIELDS = {"adIds", "adNames", "day", "account", "adType", "spend", "fbData", "gaData","campaignId", "campaignName", "adSetId", "adSetName", "adId", "adName", "productId", "optimizationGoal", "billingEvent", "country", "gender", "age", "device", "placement", "account", "autoBid", "adType"};
    private static String[] FB_FIELDS = {"count", "spend", "salesAmount", "cpc", "cps", "checkoutCR", "clicks", "impressions", "checkout", "roi", "cart"};
    private static String[] GA_FIELDS = {"cartCR", "orderAmount", "cpa", "cpc", "clicks", "orderPrice", "roi", "cart", "cr", "pays"};

    private static String[] dealPercent = {"checkoutCR", "cartCR"};
    private static String[] dealTwo = {"roi", "cr"};
    private static String[] dealMoney = { "orderPrice", "orderAmount", "salesAmount", "cps", "spend", "cpc", "cps", "cpa"};

    @Autowired
    private EcReportService ecReportService;

    @Autowired
    private EcService ecService;

    @RequestMapping(value = "report", method = RequestMethod.POST)
    public Map<String, Object> report(@RequestBody EcReportForABTestInputParam param) throws Exception {
        return ecReportService.report(param);
    }

    @RequestMapping(value = "abGraph", method = RequestMethod.POST)
    public Map<String, Object> abGraph(@RequestBody EcReportForABTestInputParam param) throws Exception {
        return ecReportService.abGraph(param);
    }

    @RequestMapping(value = "export", method = RequestMethod.GET)
    public void export(HttpServletRequest request,HttpServletResponse response) throws Exception {
        SimpleDateFormat format_job = new SimpleDateFormat("MM月dd日GHH时mm分ss秒");
        User user = (User) request.getSession().getAttribute("user");
        String fileName="细分报表-" + (StringUtil.isEmpty(user.getNickname()) ? user.getUsername() : user.getNickname()) + "-" + format_job.format(new Date());
        EcReportInputParam param = JSON.parseObject(request.getParameter("param"), EcReportInputParam.class);
        Map<String, Object> res = ecService.report(user.getOrgId(), user.getTicket(), param);
        //填充list数据
        List<Object> li = (List<Object>)res.get("list");
        if(ListUtil.isEmpty(li))
            return;
        List<Map<String,Object>> list = createExcelRecord(li, user.getLanguage());
        List<Map<String, Object>>  gather = createExcelGather(res);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ExcelUtil.createWorkBook(list, gather, param.getThs()).write(os);

        byte[] content = os.toByteArray();
        InputStream is = new ByteArrayInputStream(content);
        // 设置response参数，可以打开下载页面
        response.reset();
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename="+ new String((fileName + ".xls").getBytes(), "iso-8859-1"));
        ServletOutputStream out = response.getOutputStream();
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            bis = new BufferedInputStream(is);
            bos = new BufferedOutputStream(out);
            byte[] buff = new byte[2048];
            int bytesRead;
            // Simple read/write loop.
            while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
                bos.write(buff, 0, bytesRead);
            }
        } catch (final IOException e) {
            throw e;
        } finally {
            if (bis != null)
                bis.close();
            if (bos != null)
                bos.close();
        }
    }

    private List<Map<String, Object>> createExcelRecord(List<Object> projects, String language) {
        List<Map<String, Object>> listmap = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        map.put("sheetName", "细分报表查询数据");
        listmap.add(map);
        for (int j = 0; j < projects.size(); j++) {
            JsonObject jsonObject = new JsonObject(projects.get(j).toString());
            Map<String, Object> mapValue = new HashMap<>();
            for(int m=0;m<EXPORT_FIELDS.length;m++){
                if(jsonObject.has(EXPORT_FIELDS[m])) {
                    if("fbData".equals(EXPORT_FIELDS[m])) {
                        JsonObject fbJsonObject = new JsonObject(jsonObject.get(EXPORT_FIELDS[m]).toString());
                        for(int x=0;x<FB_FIELDS.length;x++){
                            if(fbJsonObject.has(FB_FIELDS[x])) {
                                if(Arrays.asList(dealMoney).contains(FB_FIELDS[x]))
                                    mapValue.put(EXPORT_FIELDS[m]+"-"+FB_FIELDS[x], fromFenToYuan(fbJsonObject.get(FB_FIELDS[x]).toString()));
                                else if(Arrays.asList(dealPercent).contains(FB_FIELDS[x]))
                                    mapValue.put(EXPORT_FIELDS[m] + "-" + FB_FIELDS[x], new BigDecimal(fbJsonObject.get(FB_FIELDS[x]).toString()).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP) + "%");
                                else if(Arrays.asList(dealTwo).contains(FB_FIELDS[x]))
                                    mapValue.put(EXPORT_FIELDS[m] + "-" + FB_FIELDS[x], new BigDecimal(fbJsonObject.get(FB_FIELDS[x]).toString()).setScale(2, BigDecimal.ROUND_HALF_UP));
                                else
                                    mapValue.put(EXPORT_FIELDS[m]+"-"+FB_FIELDS[x], fbJsonObject.get(FB_FIELDS[x]));
                            }
                        }
                    } else if("gaData".equals(EXPORT_FIELDS[m])) {
                        JsonObject gaJsonObject = new JsonObject(jsonObject.get(EXPORT_FIELDS[m]).toString());
                        for(int y=0;y<GA_FIELDS.length;y++){
                            if(gaJsonObject.has(GA_FIELDS[y])) {
                                if(Arrays.asList(dealMoney).contains(GA_FIELDS[y]))
                                    mapValue.put(EXPORT_FIELDS[m]+"-"+GA_FIELDS[y], fromFenToYuan(gaJsonObject.get(GA_FIELDS[y]).toString()));
                                else if(Arrays.asList(dealPercent).contains(GA_FIELDS[y]))
                                    mapValue.put(EXPORT_FIELDS[m] + "-" + GA_FIELDS[y], new BigDecimal(gaJsonObject.get(GA_FIELDS[y]).toString()).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP) + "%");
                                else if(Arrays.asList(dealTwo).contains(GA_FIELDS[y]))
                                    mapValue.put(EXPORT_FIELDS[m] + "-" + GA_FIELDS[y], new BigDecimal(gaJsonObject.get(GA_FIELDS[y]).toString()).setScale(2, BigDecimal.ROUND_HALF_UP));
                                else
                                    mapValue.put(EXPORT_FIELDS[m]+"-"+GA_FIELDS[y], gaJsonObject.get(GA_FIELDS[y]));
                            }
                        }
                    } else if("day".equals(EXPORT_FIELDS[m])) {
                        mapValue.put(EXPORT_FIELDS[m], jsonObject.get(EXPORT_FIELDS[m]));
                        //按day处理星期几
                        Week week = WeekUtil.getWeek(jsonObject.get(EXPORT_FIELDS[m]).toString());
                        if ("zh-cn".equals(language) || "zh_CN".equals(language) || "zh".equals(language) || "CN".equals(language)) {
                            mapValue.put("week", week.getChineseName());
                        } else {
                            mapValue.put("week", week.getName());
                        }
                    } else {
                        if(Arrays.asList(dealMoney).contains(EXPORT_FIELDS[m]))
                            mapValue.put(EXPORT_FIELDS[m], fromFenToYuan(jsonObject.get(EXPORT_FIELDS[m]).toString()));
                        else if(Arrays.asList(dealPercent).contains(EXPORT_FIELDS[m]))
                            mapValue.put(EXPORT_FIELDS[m], new BigDecimal(jsonObject.get(EXPORT_FIELDS[m]).toString()).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP) + "%");
                        else if(Arrays.asList(dealTwo).contains(EXPORT_FIELDS[m]))
                            mapValue.put(EXPORT_FIELDS[m], new BigDecimal(jsonObject.get(EXPORT_FIELDS[m]).toString()).setScale(2, BigDecimal.ROUND_HALF_UP));
                        else
                            mapValue.put(EXPORT_FIELDS[m], jsonObject.get(EXPORT_FIELDS[m]));
                    }
                }
            }
            listmap.add(mapValue);
        }
        return listmap;
    }

    /**
     * 加工汇总数据
     */
    private List<Map<String, Object>>  createExcelGather(Map<String, Object> res) {
        List<Map<String, Object>>  listmap = new ArrayList<>();
        if(res.get("fbSummary") != null) {
            JsonObject fbJsonObject = new JsonObject(res.get("fbSummary").toString());
            Map<String, Object> fbMap = new HashMap<>();
            for(int x=0;x<FB_FIELDS.length;x++){
                if(fbJsonObject.has(FB_FIELDS[x])) {
                    if(Arrays.asList(dealMoney).contains(FB_FIELDS[x]))
                        fbMap.put("fbData" + "-" + FB_FIELDS[x], fromFenToYuan(fbJsonObject.get(FB_FIELDS[x]).toString()));
                    else if(Arrays.asList(dealPercent).contains(FB_FIELDS[x]))
                        fbMap.put("fbData" + "-" + FB_FIELDS[x], new BigDecimal(fbJsonObject.get(FB_FIELDS[x]).toString()).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP) + "%");
                    else if(Arrays.asList(dealTwo).contains(FB_FIELDS[x]))
                        fbMap.put("fbData" + "-" + FB_FIELDS[x], new BigDecimal(fbJsonObject.get(FB_FIELDS[x]).toString()).setScale(2, BigDecimal.ROUND_HALF_UP));
                    else
                        fbMap.put("fbData" + "-" + FB_FIELDS[x], fbJsonObject.get(FB_FIELDS[x]).toString());
                }

            }
            listmap.add(fbMap);
        }
        if(res.get("gaSummary") != null) {
            JsonObject fbJsonObject = new JsonObject(res.get("gaSummary").toString());
            Map<String, Object> gaMap = new HashMap<>();
            for(int y=0;y<GA_FIELDS.length;y++){
                if(fbJsonObject.has(GA_FIELDS[y])) {
                    if(Arrays.asList(dealMoney).contains(GA_FIELDS[y]))
                        gaMap.put("gaData" + "-" + GA_FIELDS[y], fromFenToYuan(fbJsonObject.get(GA_FIELDS[y]).toString()));
                    else if(Arrays.asList(dealPercent).contains(GA_FIELDS[y]))
                        gaMap.put("gaData" + "-" + GA_FIELDS[y], new BigDecimal(fbJsonObject.get(GA_FIELDS[y]).toString()).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP) + "%");
                    else if(Arrays.asList(dealTwo).contains(GA_FIELDS[y]))
                        gaMap.put("gaData" + "-" + GA_FIELDS[y], new BigDecimal(fbJsonObject.get(GA_FIELDS[y]).toString()).setScale(2, BigDecimal.ROUND_HALF_UP));
                    else
                        gaMap.put("gaData" + "-" + GA_FIELDS[y], fbJsonObject.get(GA_FIELDS[y]).toString());
                }
            }
            listmap.add(gaMap);
        }
        return listmap;
    }

    /**
     * 分转换为元.
     *
     * @param fen
     *            分
     * @return 元
     */
    public static String fromFenToYuan(final String fen) {
        final int MULTIPLIER = 100;
        String yuan = new BigDecimal(fen).divide(new BigDecimal(MULTIPLIER)).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
        return yuan;
    }


}
